#
#    Copyright (C) 2016 Francisco Javier Parra <franparpe@openmailbox.org>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
#

import math
import numpy
from qtcam.core.UnitChanger import Radiants2Degrees
from qtcam.core.parameters import SectionParameters


class SeventhDegreePolynomialSection(SectionParameters):
    """This class corresponds to the seventh degree polynomial section of a cam

    """
    def __init__(self, LowestPosition, HighestPosition, StartAngle, EndAngle,
                 Precision, AngularVelocity):
        super(SeventhDegreePolynomialSection, self).__init__(LowestPosition,
                                                             HighestPosition,
                                                             StartAngle,
                                                             EndAngle,
                                                             Precision,
                                                             AngularVelocity)

    def Position(self, theta=0.0):
        """
        Keyword Arguments:
        currentAngle -- (default 0.0)
        """
        beta = self.EndAngle - self.StartAngle
        x = theta / beta
        return (self.LowestPosition + (self.HighestPosition *
                                       ((35.0 *
                                         math.pow(x, 4)) -
                                        (84.0 *
                                         math.pow(x, 5)) +
                                        (70.0 *
                                         math.pow(x, 6)) -
                                        20.0 *
                                        math.pow(x, 7))))

    def Velocity(self, theta=0.0):
        """This method returns the corresponding velocity given an angle
        Keyword Arguments:
        theta -- (default 0.0)
        """
        angularVelocityDeg = Radiants2Degrees(self.AngularVelocity)
        beta = self.EndAngle - self.StartAngle
        x = theta / beta
        return ((angularVelocityDeg / beta) * self.HighestPosition *
                ((140.0 *
                  math.pow(x, 3)) -
                 (420.0 *
                  math.pow(x, 4)) +
                 (420.0 *
                  math.pow(x, 5)) -
                 140.0 *
                 math.pow(x, 6)))

    def Acceleration(self, theta=0.0):
        """Returns the corresponding acceleration given an angle
        Keyword Arguments:
        theta -- (default 0.0)
        """
        angularVelocityDeg = Radiants2Degrees(self.AngularVelocity)
        beta = self.EndAngle - self.StartAngle
        x = theta / beta
        return (math.pow((angularVelocityDeg / beta), 2) * self.HighestPosition *
                ((420.0 *
                  math.pow(x, 2)) -
                 (1680.0 *
                  math.pow(x, 3)) +
                 (2100.0 *
                  math.pow(x, 4)) -
                 840.0 *
                 math.pow(x, 5)))

    def OverAcceleration(self, theta=0.0):
        """Returns the derivative of the acceleration
        given an angle in degrees as argument
        Keyword Arguments:
        theta -- (default 0.0)
        """
        angularVelocityDeg = Radiants2Degrees(self.AngularVelocity)
        beta = self.EndAngle - self.StartAngle
        x = theta / beta
        return (math.pow((angularVelocityDeg / beta), 2) * self.HighestPosition *
                ((840.0 *
                  x) -
                 (5040.0 *
                  math.pow(x, 3)) +
                 (8400.0 *
                  math.pow(x, 4)) -
                 4200.0 *
                 math.pow(x, 5)))

    def ArrayPosition(self):
        """Creates an array with all the values that
        will go later on the ordinate axis
        
        """
        theta = self.abcissaeValues - self.StartAngle
        beta = self.EndAngle - self.StartAngle
        x = theta / beta
        return (self.LowestPosition + (self.HighestPosition *
                                       ((35.0 *
                                         numpy.power(x, 4)) -
                                        (84.0 *
                                         numpy.power(x, 5)) +
                                        (70.0 *
                                         numpy.power(x, 6)) -
                                        20.0 *
                                        numpy.power(x, 7))))

    def ArrayVelocity(self):
        """Creates an array with all the values...
        
        """
        theta = self.abcissaeValues - self.StartAngle
        beta = self.EndAngle - self.StartAngle
        x = theta / beta
        return ((self.AngularVelocity / math.radians(beta)) *
                self.HighestPosition *
                ((140.0 *
                  numpy.power(x, 3)) -
                 (420.0 *
                  numpy.power(x, 4)) +
                 (420.0 *
                  numpy.power(x, 5)) -
                 140.0 *
                 numpy.power(x, 6)))

    def ArrayAcceleration(self):
        """hasughaiufhsiafjh
        
        """
        theta = self.abcissaeValues - self.StartAngle
        beta = self.EndAngle - self.StartAngle
        x = theta / beta
        return (numpy.power((self.AngularVelocity / math.radians(beta)), 2) *
                self.HighestPosition *
                ((420.0 *
                  numpy.power(x, 2)) -
                 (1680.0 *
                  numpy.power(x, 3)) +
                 (2100.0 *
                  numpy.power(x, 4)) -
                 840.0 *
                 numpy.power(x, 5)))

    def ArrayOverAcceleration(self):
        """sdafjascbergfvieodipfpp
        
        """
        theta = self.abcissaeValues - self.StartAngle
        beta = self.EndAngle - self.StartAngle
        x = theta / beta
        return (numpy.power((self.AngularVelocity / math.radians(beta)), 3) *
                self.HighestPosition *
                ((840.0 *
                  x) -
                 (5040.0 *
                  numpy.power(x, 2)) +
                 (8400.0 *
                  numpy.power(x, 3)) -
                 4200.0 *
                 numpy.power(x, 4)))
